﻿using System;
using System.Linq;
using System.Xml;
using PSE.Deployment.Engine;
using PSE.Deployment.Engine.Enums;
using PSE.Deployment.Engine.Interfaces;
using PSE.Deployment.SetupBase;
using PSE.Deployment.SetupBase.Configuration.Enums;
using PSE.Deployment.SetupBase.Parameter;
using Sinacor.Deployment.Setup.Main;
using PSE.Deployment.SetupBase.Parameter.Enums;
using PSE.Deployment.Util;
using System.Collections.Generic;
using PSE.Deployment.SetupBase.Configuration;
using System.IO;

namespace Sinacor.Deployment.Setup.Install.Steps
{
    public class UpdateInterfaceLayerVersion : BaseStep
    {
        public UpdateInterfaceLayerVersion(IStepGroup parent)
            : base(parent)
        {
            this.Id = "UpdateInterfaceLayerVersion";
            this.Description = "Atualização das versões dos módulos";
            this.ErrorBehavior = StepErrorBehavior.NotifyParent;
            this.NavigationBehavior = StepNavigationBehavior.NextCancel;

            this.ResetProgress(2);
        }

        public override void Execute()
        {
            this.ResetProgress(2);

            UpdateConfig("Sinacor.exe.config");

            UpdateConfig("SinacorHelp.exe.config");
        }

        private void UpdateConfig(string fileName)
        {
            try
            {
                XmlDocument document = new XmlDocument();

                string path = SetupMainFactory.GetInstance<SinacorMain>().Parameter.InstallationPath + @"Sinacor\UI\Application\" + fileName;

                this.IncrementProgress(Description);

                if (System.IO.File.Exists(path))
                {
                    document.Load(path);

                    List<Group> groups = SetupMainFactory.GetInstance().OriginalConfiguration.SystemInfo.Groups.SelectDeep(g => g.SubGroups).SelectDeep(g => g.Dependencies).ToList();

                    XmlNode modulesNode = document.SelectSingleNode("configuration/modules/installedModules");

                    if (modulesNode != null)
                    {
                        Dictionary<string, string> centuraExecutables = this.GetCenturaExecutables(modulesNode);

                        modulesNode.RemoveAll();

                        XmlElement element;
                        System.Xml.XmlAttribute attribute;

                        foreach (ModuleVersion moduleVersion in SetupMainFactory.GetInstance<SinacorMain>().Parameter.Versions)
                        {
                            element = document.CreateElement("module");

                            attribute = document.CreateAttribute("name");
                            attribute.Value = moduleVersion.Id;
                            element.Attributes.Append(attribute);

                            Group group = groups.Find(g => g.Module.Id == moduleVersion.Id);

                            if (group != null)
                            {
                                foreach (ActionBase action in group.Actions)
                                {
                                    if (action is PSE.Deployment.SetupBase.Configuration.Actions.Copy)
                                    {
                                        if (((PSE.Deployment.SetupBase.Configuration.Actions.Copy)action).Folders.Count > 0)
                                        {
                                            attribute = document.CreateAttribute("folder");
                                            attribute.Value = Path.GetFileName(Path.GetDirectoryName(((PSE.Deployment.SetupBase.Configuration.Actions.Copy)action).Folders[0].Destination));
                                            element.Attributes.Append(attribute);
                                        }
                                    }
                                }
                            }

                            attribute = document.CreateAttribute("version");
                            attribute.Value = moduleVersion.Version.ToString();
                            element.Attributes.Append(attribute);

                            attribute = document.CreateAttribute("centuraPath");
                            attribute.Value = string.Empty;
                            element.Attributes.Append(attribute);

                            attribute = document.CreateAttribute("centuraExecutable");
                            attribute.Value = centuraExecutables.ContainsKey(moduleVersion.Id) ? centuraExecutables[moduleVersion.Id] : string.Empty;
                            element.Attributes.Append(attribute);

                            modulesNode.AppendChild(element);
                        }

                        //TODO: mudar forma de criar o modulo kernel+
                        //Criar modulo Kernel+
                        element = document.CreateElement("module");
                        attribute = document.CreateAttribute("name");
                        attribute.Value = "KNL";
                        element.Attributes.Append(attribute);

                        attribute = document.CreateAttribute("version");
                        attribute.Value = "1.0.0.0";
                        element.Attributes.Append(attribute);

                        modulesNode.AppendChild(element);
                    }

                    document.Save(path);
                }
            }
            catch (Exception ex)
            {
                SetupMainFactory.GetInstance<SinacorMain>().WriteStepLog(this, string.Format("Não foi possível alterar o arquivo Sinacor.exe.config \n Error: {0}", ex.Message));
            }
        }

        public override void Undo()
        {
            if (SetupMainFactory.GetInstance<SinacorMain>().Parameter.SetupMode == SetupMode.Install)
            {
                this.DecrementProgress();
            }
        }

        private Dictionary<string, string> GetCenturaExecutables(XmlNode modules)
        {
            Dictionary<string, string> centuraExecutables = new Dictionary<string, string>();

            foreach (XmlNode module in modules.ChildNodes)
            {
                if (module.Attributes["name"] != null &&
                    module.Attributes["centuraExecutable"] != null)
                {
                    centuraExecutables.Add(module.Attributes["name"].Value, module.Attributes["centuraExecutable"].Value);
                }
            }

            return centuraExecutables;
        }
    }
}
